'use strict';

const { Controller } = require('egg');
const path = require('path')
const fs = require('fs')
const OSS = require('ali-oss')
// 存放文件的绝对目录
const FILE_PATH_UPLOAD = path.resolve(__dirname, '../../uploadFiles')



class HomeController extends Controller {
	// 检查文件接口
	async checkFile() {
		const { ctx } = this
		const { hash } = ctx.request.body
		// 获取已经上传过文件列表
		const uploadFilesList = (await fs.promises.readdir(FILE_PATH_UPLOAD)).map(pathname => path.join(FILE_PATH_UPLOAD, pathname))
		// 查看一下是否存在一个目录或者文件和我们传递过来的hash一样
		const exist = uploadFilesList.find(pathname => {
			// 获取文件名字
			const { name } = path.parse(pathname)
			// 查看hash是否存在name
			return name === hash
		})

		// 是否存在该目录
		if (exist) {
			// 存在
			// 分辨是文件还是文件夹
			// 返回值true 是文件夹
			// 返回值false 是文件
			const isDir = (await fs.promises.stat(exist)).isDirectory();
			// 存在文件夹
			if (isDir) {
				ctx.body = {
					code: 202,
					message: '文件已经上传部分， 请继续上传',
					data: {
						uploaded: true,
						existsChunks: await fs.promises.readdir(exist)
					}
				}
				// 存在文件
			} else {
				ctx.body = {
					code: 201,
					message: '文件已经上传, 秒传成功！',
					data: {
						uploaded: true,
					}
				}
			}

		} else {
			// 不存在
			ctx.body = {
				code: 200,
				message: '文件未上传，请开始上传',
				data: {
					uploaded: false,
				}
			}
		}
	}
	// 上传文件接口
	async upload() {
		const { ctx } = this;
		const file = ctx.request.files[0];
		const filename = file.filename
		const filepath = file.filepath
		const hash = filename.split('-')[0]

		try {
			const exist = fs.existsSync(path.join(FILE_PATH_UPLOAD, hash));
			if (!exist) await fs.promises.mkdir(path.join(FILE_PATH_UPLOAD, hash))
			await fs.promises.copyFile(filepath, path.join(FILE_PATH_UPLOAD, hash, filename))
		} finally {
			ctx.cleanupRequestFiles();
		}

		ctx.body = {
			code: 200,
			data: null,
			message: `${filename} 上传成功`
		};
	}
	// 合并文件 
	async mergeFile() {
		const { ctx } = this;
		const { hash, extname } = ctx.request.body;
		// 获取hash所在目录
		const hashDir = path.join(FILE_PATH_UPLOAD, hash);
		// 验证目录是否存在
		if (fs.existsSync(hashDir)) {


			const sourceFiles = (await fs.promises.readdir(hashDir)).sort((a, b) => {
				const aIndex = path.parse(a).name.split('-')[1]
				const bIndex = path.parse(b).name.split('-')[1];
				return +aIndex - +bIndex
			}).map(v => path.join(hashDir, v))


			const targetFile = path.join(FILE_PATH_UPLOAD, hash + extname)

			this.streamMergeFile(sourceFiles, targetFile)

			ctx.body = {
				code: 200,
				message: '文件合并成功'
			}

		} else {
			ctx.body = {
				code: 400,
				message: '请求合并的文件不存在'
			}
		}
	}

	async streamMergeFile(sourceFiles, targetFile) {
		const write = fs.createWriteStream(targetFile);
		return await this.readFileAndWrireFile(sourceFiles, write)
	}

	async readFileAndWrireFile(sourceFiles = [], write) {
		if (sourceFiles.length === 0) {
			write.end('结束')
		}
		const source = sourceFiles.shift();

		const read = fs.createReadStream(source);

		read.pipe(write, { end: false });

		read.on('end', () => {
			this.readFileAndWrireFile(sourceFiles, write)
		})
	}

	async ossUpload() {
		const { ctx } = this;
		const file = ctx.request.files[0]
		const filepath = file.filepath
		const filename = file.filename
		
		const client = new OSS({
			// yourregion填写Bucket所在地域。以华东1（杭州）为例，Region填写为oss-cn-hangzhou。
			region: 'oss-cn-hangzhou',
			// 阿里云账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维，请登录RAM控制台创建RAM用户。
			accessKeyId: 'LTAI5tBfqEpp4VZUrmhavEtK',
			accessKeySecret: '4RFY8uPujxzLz2vSprHRsKgrvXtqJn',
			// 填写Bucket名称。
			bucket: '2005a-10',
		});

		const headers = {
			// 指定Object的存储类型。
			'x-oss-storage-class': 'Standard',
			// 指定Object的访问权限。
			'x-oss-object-acl': 'private',
			// 设置Object的标签，可同时设置多个标签。
			'x-oss-tagging': 'Tag1=1&Tag2=2',
			// 指定PutObject操作时是否覆盖同名目标Object。此处设置为true，表示禁止覆盖同名Object。
			'x-oss-forbid-overwrite': 'true',
		};

		async function put() {
			try {
				// 填写OSS文件完整路径和本地文件的完整路径。OSS文件完整路径中不能包含Bucket名称。
				// 如果本地文件的完整路径中未指定本地路径，则默认从示例程序所属项目对应本地路径中上传文件。
				const result = await client.put(filename, path.normalize(filepath)
					// 自定义headers
					//,{headers}
				);
				return result
			} catch (e) {
				console.log(e);
			}
		}

		const result = await put();

		ctx.body = {
			code: 200,
			data: {
				url: result
			}
		}

	}
}

module.exports = HomeController;
